# -*- coding: utf-8 -*-
"""
版权所有：J哥
微信号：wws_0904
author : Laity
Description: user序列化器

model 指明参照哪个模型类
fields 指明为模型类的哪些字段生成
allow 协议
['id', 'username', 'password', 'password2', 'email', 'sms_code', 'allow']  处理id都要校验
序列化字段:  ['id', 'username','email']  模型转字典 传给前端的
反序列化字段： ['username', 'password', 'password2', 'email', 'sms_code', 'allow']
需要校验字段: ['username', 'password', 'password2', 'email', 'sms_code', 'allow']
已存在字段: ['id', 'username', 'password', 'email']
write_only 表示只做反序列化
read_only  表示只做序列化
extra_kwargs 指定在模型类中需要修改的字段
"""
import re
from rest_framework import serializers
from .models import User
from django_redis import get_redis_connection


class createUserSerializer(serializers.ModelSerializer):
    password2 = serializers.CharField(label="确认密码", write_only=True)
    sms_code = serializers.CharField(label="验证码", write_only=True)
    allow = serializers.CharField(label="同意协议", write_only=True)
    token = serializers.CharField(label="token", read_only=True)

    class Meta:
        model = User
        fields = ['id', 'username', 'password', 'password2', 'email', 'sms_code', 'allow', 'token']
        extra_kwargs = {
            'username': {
                'min_length': 5,
                'max_length': 20,
                'error_messages': {  # 自定义校验错误信息
                    'min_length': '仅允许5-20个字符的用户名',
                    'max_length': '仅允许5-20个字符的用户名',
                }
            },
            'password': {
                'write_only': True,  # 表示只做反序列化
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    #
    # 　　　┏┓　　　┏┓
    # 　　┏┛┻━━━┛┻┓
    # 　　┃　　　　　　　 ┃ 　
    # 　　┃　　　━　　　 ┃
    # 　　┃　＞　　　＜┃
    # 　　┃　　　　　　　 ┃
    # 　　┃ . ⌒　..┃
    # 　　┃　　　　　　　 ┃
    # 　　┗━┓　　　┏━┛
    # 　　　　┃　　　┃　Codes are far away from bugs with the animal protecting　　　　　　　
    # 　　　　┃　　　┃ 神兽保佑,代码无bug
    # 　　　　┃　　　┃　　　　　　　　　　　
    # 　　　　┃　　　┃ 　　　　　　
    # 　　　　┃　　　┃
    # 　　　　┃　　　┃　　　　　　　　　　　
    # 　　　　┃　　　┗━━━┓
    # 　　　　┃　　　　　　　┣┓
    # 　　　　┃　　　　　　　┏┛
    # 　　　　┗┓┓┏━┳┓┏┛
    # 　　　　　┃┫┫　┃┫┫
    # 　　　　　┗┻┛　┗┻┛

    def validate_email(self, value):
        """自定义校验逻辑：校验邮箱"""
        if not re.match(r'\w{1,}@\w{1,}.(com|cn|com.cn)', value):
            raise serializers.ValidationError("邮箱格式有误")
        return value

    def validate_allow(self, value):
        """
        同意协议校验
        注意：前端返回的布尔值 是小写的(true、false)
        """
        if value != "true":
            raise serializers.ValidationError("请同意协议")
        return value

    def validate(self, attrs):
        """
        联合校验逻辑：校验多个值
        :param attrs: 前端传来的字段数据
        :return: attrs
        """
        pwd = attrs["password"]
        pwd2 = attrs["password2"]
        if pwd2 != pwd:
            raise serializers.ValidationError("两次密码不一致")

        email = attrs["email"]
        email = email.split("@")[0]
        redis = get_redis_connection("mailcodes")
        real_email_code = redis.get(f"mail_{email}")
        # 向redis存储数据时都是以字符串进行存储的，取出来后都是bytes类型
        # if real_email_code is None or attrs["smscode"] != real_email_code.decode():  # 经典代码
        if real_email_code is None:
            raise serializers.ValidationError("无效验证码")
        if attrs["sms_code"] != real_email_code.decode():
            raise serializers.ValidationError("验证码错误")

        return attrs

    #
    #        ┏┓　　　┏┓+ +
    # 　　　┏┛┻━━━┛┻┓ + +
    # 　　　┃　　　　　　　┃ 　
    # 　　　┃　　　━　　　┃ ++ + + +
    # 　　 ████━████ ┃+
    # 　　　┃　　　　　　　┃ +
    # 　　　┃　　　┻　　　┃
    # 　　　┃　　　　　　　┃ + +
    # 　　　┗━┓　　　┏━┛
    # 　　　　　┃　　　┃　　　　　　　　　　　
    # 　　　　　┃　　　┃ + + + +
    # 　　　　　┃　　　┃　　　　Codes are far away from bugs with the animal protecting　　　
    # 　　　　　┃　　　┃ + 　　　　神兽保佑,代码无bug　　
    # 　　　　　┃　　　┃
    # 　　　　　┃　　　┃　　+　　　　　　　　　
    # 　　　　　┃　 　　┗━━━┓ + +
    # 　　　　　┃ 　　　　　　　┣┓
    # 　　　　　┃ 　　　　　　　┏┛
    # 　　　　　┗┓┓┏━┳┓┏┛ + + + +
    # 　　　　　　┃┫┫　┃┫┫
    # 　　　　　　┗┻┛　┗┻┛+ + + +
    #
    def create(self, validated_data):
        """
        重写 CreateAPIView 的 create 方法：因为有些字段不需要存储（需要删除掉）
        :param validated_data: 反序列化的字典
        :return:
        """
        del validated_data["password2"]
        del validated_data["sms_code"]
        del validated_data["allow"]

        # 把要存的密码取出来
        password = validated_data.pop("password")
        # 创建用户模型对象，进行赋值
        user = User(**validated_data)
        # 再对密码加密
        user.set_password(password)
        # 存储数据库
        user.save()

        # JWT的使用
        from rest_framework_jwt.settings import api_settings

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return user
